package dnufractal;

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class tcmpr {
  public transient int[][] morigdata, mresdata;
  public int datasz;
  public tcntblk cntblk;//верхушка дерева
  private BitSet bs; private int bsct;
  public DataOutputStream dos;
  public DataInputStream dis;
  public void wbit(boolean a){
    bs.set(bsct, a);
    bsct++;
  }
  public boolean rbit(){
    bsct++;
    return bs.get(bsct-1);
  }
  public void openfile(String afn){
    try {
      BufferedImage image = ImageIO.read(new File(afn));
      int sz=Math.min(image.getWidth(),image.getHeight());
      int sz2=1;
      for(int i=1;i<=sz;i*=2)sz2=i;
      morigdata=new int[sz2][sz2];
      for(int ix=0;ix<sz2;ix++)
        for(int iy=0;iy<sz2;iy++){
          int rgb = image.getRGB(ix, iy);
          Color c = new Color(rgb);
//          if(c.getRed()!=0){System.out.println(c.getRed()+"-> "+c.getAlpha());}
          morigdata[ix][iy]=(c.getRed()+c.getGreen()+c.getBlue())/3;
        }
//      Image image = ImageIO.read(file);
    } catch (IOException ex) {
      Logger.getLogger(tcmpr.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
  public void savefile(String afn){
    BufferedImage image=new BufferedImage(datasz, datasz, BufferedImage.TYPE_INT_RGB);
      for(int ix=0;ix<datasz;ix++)
        for(int iy=0;iy<datasz;iy++){
          int b=morigdata[ix][iy];
//          System.out.println(b);
          Color c= new Color(b,b,b);
          image.setRGB(ix, iy, c.getRGB());
        }
    try {
      ImageIO.write(image, "bmp", new File(afn));
    } catch (IOException ex) {
      Logger.getLogger(tcmpr.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
  public void tofile(String afn){
    bs=new BitSet(); bsct=0;
    ByteArrayOutputStream bas=new ByteArrayOutputStream(1024);
    dos=new DataOutputStream(bas);
    cntblk.save();
    try {
      FileOutputStream fos = new FileOutputStream(afn);
      ObjectOutputStream out = new ObjectOutputStream(fos);
      out.writeObject(bas.toByteArray());
      out.writeObject(bs);
      out.close();
      bs=null; dos=null;
    } catch (IOException ex) {
      Logger.getLogger(tcmpr.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
  public void frfile(String afn){
    try {
      FileInputStream fis = new FileInputStream(afn);
      ObjectInputStream in = new ObjectInputStream(fis);
      byte[] ba = (byte[]) in.readObject();
      ByteArrayInputStream bis = new ByteArrayInputStream(ba);
      dis = new DataInputStream(bis);
      bs = (BitSet) in.readObject(); bsct=0;
      rbit();
      cntblk=new tcntblk();
      cntblk.cmpr=this;
      cntblk.load();
    } catch (Exception ex) {
      Logger.getLogger(tcmpr.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
  public void cmp(double adelta){
    datasz=morigdata.length;
//    mresdata=new int[datasz][datasz];
    cntblk=new tcntblk();
    cntblk.cmpr=this;
    cntblk.map(0, 0, datasz, adelta*datasz*datasz);
  }
  public void ucmp(int asz){
    morigdata=new int[asz][asz];
    mresdata=new int[asz][asz];
    datasz=asz;
    for(int i=0;i<10;i++){
      cntblk.ucmp(0,0,asz);
      int[][] m=morigdata;
      morigdata=mresdata;
      mresdata=m;
    }
  }
  public int[][] msht(int aorigx, int aorigy, int aorigsz, int aressz, byte arotation, boolean amirror){
//    System.out.println(aorigx+" "+ aorigy+ " "+ aorigsz+" "+ aressz);
    int res[][]=new int[aressz][aressz];
    int m=aorigsz/aressz;
    for(int ix=0;ix<aressz;ix++)
      for(int iy=0;iy<aressz;iy++){
        int pix=0;
        for(int jx=0;jx<m;jx++)
          for(int jy=0;jy<m;jy++)
            pix+=morigdata[aorigx+ix*m+jx][aorigy+iy*m+jy];
        if(arotation==0)res[ix][iy]=pix/(m*m);else
        if(arotation==1)res[aressz-iy-1][ix]=pix/(m*m);else
        if(arotation==2)res[aressz-ix-1][aressz-iy-1]=pix/(m*m);else
        if(arotation==3)res[iy][aressz-ix-1]=pix/(m*m);
      }
   if(!amirror)return res;
   int res1[][]=new int[aressz][aressz];
   for(int ix=0;ix<aressz;ix++)
     for(int iy=0;iy<aressz;iy++)
        res1[ix][iy]=res[aressz-ix-1][iy];
   return res1;
  }
  public int sum(int aorigx, int aorigy, int asz){
    int res=0;
    for(int ix=0; ix<asz; ix++)
      for(int iy=0; iy<asz; iy++)
        res+=morigdata[aorigx+ix][aorigy+iy];
    return res;
  }

}
